package com.erp.framework.model.dao;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;

import javax.ejb.EJBObject;
import javax.mail.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import javax.transaction.UserTransaction;

import com.erp.framework.SimpleConstants;
import com.erp.framework.util.CommonUtil;
import com.erp.framework.util.logger.Logger;

public class ServiceLocator implements SimpleConstants{

    private static ServiceLocator me;
    private static String reportServer = null;
    private static String reportLoginUser = null;
    private static String reportLoginPassword = null;

    private InitialContext context = null;
    private Map homeInterfaces = null;
    static javax.sql.DataSource dbDataSource;

    /** Creates new ServiceLocator */
    public ServiceLocator() {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        String appServerType = SimpleConstants.APP_SERVER_JBOSS;
        homeInterfaces = new HashMap();

        try {
            appServerType = System.getProperty(SimpleConstants.SYS_APP_SERVER_TYPE);
            if (SimpleConstants.APP_SERVER_WEB_SPHERE.equalsIgnoreCase(appServerType)) {
                /*
                 * Websphere way -------------
                 */
                java.util.Properties p = new java.util.Properties();
                p.put(Context.PROVIDER_URL, "IIOP:///");
                p.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");
                context = new InitialContext(p);
            } else {
                // default JBoss
                /*
                 * JBoss way -------------
                 */
                context = new InitialContext();
            }
            Logger.debug(" * SYSTEM FREE MEM: " + CommonUtil.formatBytes(Runtime.getRuntime().freeMemory()) + ", TOT MEM: "
                    + CommonUtil.formatBytes(Runtime.getRuntime().totalMemory()));
        } catch (Exception e) {
            Logger.logExceptions(this, e);
        } finally {
            try {
                if (rs != null)
                    rs.close();
                if (stmt != null)
                    stmt.close();
                if (conn != null && !conn.isClosed())
                    conn.close();
            } catch (Exception e) {
                Logger.logExceptions(this, e);
            }
        }
    }

    public static String getReportServer() {
        return reportServer;
    }

    public static String getReportLoginUser() {
        return reportLoginUser;
    }

    public static String getReportLoginPassword() {
        return reportLoginPassword;
    }

    public static ServiceLocator getInstance() {
        try {
            if (me == null) {
                me = new ServiceLocator();
            }
        } catch (Exception e) {
            Logger.logExceptions(e);
        }

        return me;
    }

    /**
     * Convert serialized string into EJBHome
     */
    public EJBObject getService(String id) {
        EJBObject ejbObject = null;
        try {
            byte[] bytes = new String(id).getBytes();
            InputStream io = new ByteArrayInputStream(bytes);
            ObjectInputStream os = new ObjectInputStream(io);
            javax.ejb.Handle handle = (javax.ejb.Handle) os.readObject();

            ejbObject = handle.getEJBObject();
        } catch (Exception e) {
            Logger.logExceptions(this, e);
        }
        return ejbObject;
    }

    protected String getId(EJBObject session) {
        String id = null;
        try {
            javax.ejb.Handle handle = session.getHandle();
            ByteArrayOutputStream fo = new ByteArrayOutputStream();
            ObjectOutputStream so = new ObjectOutputStream(fo);
            so.writeObject(handle);
            so.flush();
            so.close();

            id = new String(fo.toByteArray());
        } catch (Exception e) {
            Logger.logExceptions(this, e);
        }
        return id;
    }

    public Object getHome(String name, Class clazz) {
        Object obj = null;
        try {
            Object objref = context.lookup(name);
            obj = PortableRemoteObject.narrow(objref, clazz);
        } catch (Exception e) {
            Logger.logExceptions(this, e);
        }
        return obj;
    }
    
    //old style
//    public EJBHome getHome(String name, Class clazz) {
//        EJBHome home = null;
//        try {
//            if (home == null) {
//                Object objref = context.lookup(name);
//                home = (EJBHome) PortableRemoteObject.narrow(objref, clazz);
//            }
//        } catch (Exception e) {
//            Logger.logExceptions(this, e);
//        }
//
//        return home;
//    }

    public InitialContext getInitialContext() {
        return context;
    }

    public Connection getDBConnection() {
        Connection connection = null;
        ResourceBundle appRS = null;
        try {
            appRS = ResourceBundle.getBundle("app");
            String dbDriver = appRS.getString("app.db.driver");
            String dbUrl = appRS.getString("app.db.url");
            String dbUser = appRS.getString("app.db.user");
            String dbPasswd = appRS.getString("app.db.passwd");

            Class.forName(dbDriver).newInstance();
            connection = DriverManager.getConnection(dbUrl, dbUser, dbPasswd);

        } catch (Exception e) {
            Logger.logExceptions(this, e);
        }

        return connection;
    }

    public Connection getDSDBConnection() {
        Connection connection = null;

        String appServerType = SimpleConstants.APP_SERVER_JBOSS;
        try {
            if (ServiceLocator.dbDataSource == null) {

                appServerType = System.getProperty(SimpleConstants.SYS_APP_SERVER_TYPE);
                if (SimpleConstants.APP_SERVER_WEB_SPHERE.equalsIgnoreCase(appServerType)) {

                    /*
                     * Websphere way -------------
                     */
                    ServiceLocator.dbDataSource = (javax.sql.DataSource) context.lookup(SimpleConstants.DATA_SOURCE_NAME);
                } else {

                    /*
                     * JBoss way -------------
                     */
                    ServiceLocator.dbDataSource = (javax.sql.DataSource) context.lookup("java:" + SimpleConstants.DATA_SOURCE_NAME);
                }

                // WebLogic way
                // this.dbDataSource = (javax.sql.DataSource) context.lookup
                // ("DS");

            }

            connection = ServiceLocator.dbDataSource.getConnection();
        } catch (Exception e) {
            Logger.logExceptions(this, e);
        }

        return connection;
    }

    public UserTransaction getUserTransaction() {
        UserTransaction usrTrans = null;

        String appServerType = SimpleConstants.APP_SERVER_JBOSS;
        try {
            appServerType = System.getProperty(SimpleConstants.SYS_APP_SERVER_TYPE);
            if (SimpleConstants.APP_SERVER_WEB_SPHERE.equalsIgnoreCase(appServerType)) {

                /*
                 * Websphere way -------------
                 */
                usrTrans = (UserTransaction) context.lookup("jta/usertransaction");
            } else {
                /*
                 * JBoss way -------------
                 */
                usrTrans = (UserTransaction) context.lookup("UserTransaction");
            }
        } catch (Exception e) {
            Logger.logExceptions(this, e);
        }

        return usrTrans;
    }

    public void userTransactionRollBack(UserTransaction ut) throws Exception {
        try {
            if (ut.getStatus() == javax.transaction.Status.STATUS_ACTIVE) {
                ut.rollback();
            }
        } catch (Exception e) {
            throw e;
        }
    }

    public Session getMailSession() {
        Session session = null;
        try {
            session = (Session) PortableRemoteObject.narrow(context.lookup("java:Mail"), Session.class);
        } catch (javax.naming.NamingException e) {
            Logger.logExceptions(this, e);
        }
        return session;
    }
}
